﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;

namespace Gmantis.Controls
{
    public class ObservableCollection<T> : Collection<T>, INotifyCollectionChanged
    {
        // Events
        public event NotifyCollectionChangedEventHandler CollectionChanged;

        public event NotifyCollectionChangedEventHandler CollectionChanging;

        // Methods
        protected override void ClearItems()
        {
            NotifyCollectionChangedEventArgs e = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset);
            this.OnCollectionChanging(e);
            base.ClearItems();
            this.OnCollectionChanged(e);
        }

        protected override void InsertItem(int index, T item)
        {
            NotifyCollectionChangedEventArgs e = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item, index);
            this.OnCollectionChanging(e);
            base.InsertItem(index, item);
            this.OnCollectionChanged(e);
        }

        private void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
        {
            if (this.CollectionChanged != null)
            {
                this.CollectionChanged(this, e);
            }
        }

        private void OnCollectionChanging(NotifyCollectionChangedEventArgs e)
        {
            if (this.CollectionChanging != null)
            {
                this.CollectionChanging(this, e);
            }
        }

        protected override void RemoveItem(int index)
        {
            T changedItem = base[index];
            NotifyCollectionChangedEventArgs e = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, changedItem, index);
            this.OnCollectionChanging(e);
            base.RemoveItem(index);
            this.OnCollectionChanged(e);
        }

        public void ResetItems(IEnumerable<T> newItems)
        {
            NotifyCollectionChangedEventArgs e = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset);
            this.OnCollectionChanging(e);
            base.ClearItems();
            foreach (T local in newItems)
            {
                base.InsertItem(base.Count, local);
            }
            this.OnCollectionChanged(e);
        }

        protected override void SetItem(int index, T item)
        {
            T oldItem = base[index];
            NotifyCollectionChangedEventArgs e = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, item, oldItem, index);
            this.OnCollectionChanging(e);
            base.SetItem(index, item);
            this.OnCollectionChanged(e);
        }
    }
}
